﻿using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using ERP.Business.DataTypes.Users;
using ERP.Business.DataTypes.Employee;
using ERP.Framework.Components.Utilities.TracingHelper;
using ERP.Framework.Components.DatabaseHelper.Providers;
using ERP.Framework.Components.DatabaseHelper;
using System.Data;
using System.Text;
using System.Xml;
using ERP.Framework.Components.SerializationHelper;
using ERP.Business.DataTypes.BaseTypes;

namespace ERP.Business.Services.Users
{
    public class UsersService //: IUsersService
    {
        /*
        #region Constants

        private const string TRACING_CATEGORY = "ERP.Business.Services.Users.UsersManagement.UsersManager";
        private const string SP_GET_USER_INFO_BY_USERNAME = "SP_USERS_GET_INFO_BY_USERNAME";
        private const string SP_GET_USER_INFO_BY_USER_ID = "SP_USERS_GET_INFO_BY_USER_ID";
        private const string SP_CHECK_USER_EXISTANCE = "SP_USERS_CHECK_USER_EXISTANCE";
        private const string SP_UPD_INS_USER_INFO = "SP_USERS_INSERT_UPDATE";
        private const string PARAM_USERNAME = "username";
        private const string PARAM_PASSWORD = "password";
        private const string PARAM_USER_ID = "id";
        private const string PARAM_EMPLOYEE_ID = "employeeId";
        private const string PARAM_USER_STATUS = "status";

        #endregion

        /// <summary>
        /// Return user info depending on the username
        /// </summary>
        /// <param name="username">username</param>
        /// <returns>User's info</returns>
        public User GetUserByUsername(string username)
        {
            TraceUtil.Write(TRACING_CATEGORY, "GetUserByUsername : Start", DateTime.Now);
            GeneralDatabaseProvider con = new GeneralDatabaseProvider(DatabaseConstants.AdministrationDatabase);
            ParametersCollection param = new ParametersCollection();
            param.AddParameter(PARAM_USERNAME, username, ParameterType.String, ERP.Framework.Components.DatabaseHelper.ParameterDirection.InParameter);
            DataTable table = con.Read(ERP.Framework.Components.DatabaseHelper.CommandType.StoredProcedure, SP_GET_USER_INFO_BY_USERNAME, param);

            User user = null;
            if (table != null && table.Rows.Count > 0)
            {
                table.TableName = "User";
                StringBuilder sb = new StringBuilder();
                using (XmlWriter x = XmlWriter.Create(sb))
                {
                    table.WriteXml(x);
                }
                user = (User)XmlSerializingManager.DeserializeObject<User>(sb.ToString());
            }

            TraceUtil.Write(TRACING_CATEGORY, "GetUserByUsername : End", DateTime.Now);

            return user;
        }

        /// <summary>
        /// Return user info depending on the user's id
        /// </summary>
        /// <param name="userId">user's id</param>
        /// <returns>User's info</returns>
        public User GetUserByUserID(string userId)
        {
            TraceUtil.Write(TRACING_CATEGORY, "GetUserByUserID : Start", DateTime.Now);
            GeneralDatabaseProvider con = new GeneralDatabaseProvider(DatabaseConstants.AdministrationDatabase);
            ParametersCollection param = new ParametersCollection();
            param.AddParameter(PARAM_USER_ID, userId, ParameterType.String, ERP.Framework.Components.DatabaseHelper.ParameterDirection.InParameter);
            DataTable table = con.Read(ERP.Framework.Components.DatabaseHelper.CommandType.StoredProcedure, SP_GET_USER_INFO_BY_USER_ID, param);

            User user = null;
            if (table != null && table.Rows.Count > 0)
            {
                table.TableName = "User";
                StringBuilder sb = new StringBuilder();
                using (XmlWriter x = XmlWriter.Create(sb))
                {
                    table.WriteXml(x);
                }
                user = (User)XmlSerializingManager.DeserializeObject<User>(sb.ToString());
            }

            TraceUtil.Write(TRACING_CATEGORY, "GetUserByUserID : End", DateTime.Now);

            return user;
        }

        /// <summary>
        /// Check if username already used
        /// </summary>
        /// <param name="username">username</param>
        /// <returns>result</returns>
        public bool CheckUsernameExistance(string username)
        {
            TraceUtil.Write(TRACING_CATEGORY, "GetUserByUserID : Start", DateTime.Now);

            GeneralDatabaseProvider con = new GeneralDatabaseProvider(DatabaseConstants.AdministrationDatabase);
            ParametersCollection p = new ParametersCollection();
            p.AddParameter(new Parameter(PARAM_USERNAME, username, ParameterType.String));
            object result = con.ReadScalar(ERP.Framework.Components.DatabaseHelper.CommandType.StoredProcedure, SP_CHECK_USER_EXISTANCE, p);
            bool bolRes = false;

            if (result != null)
                bool.TryParse(result.ToString(), out bolRes);

            TraceUtil.Write(TRACING_CATEGORY, "GetUserByUserID : End", DateTime.Now);
            return bolRes;
        }

        /// <summary>
        /// Create new user
        /// </summary>
        /// <param name="user">New <see cref="User"/></param>
        /// <returns>true if user created</returns>        
        public bool CreateUser(User user)
        {
            user.DirtyFlag = DirtyFlag.Insert;
            return UpdateUserInfo(user);
        }

        /// <summary>
        /// Create new user
        /// </summary>
        /// <param name="username">username</param>
        /// <param name="password">password</param>
        /// <param name="employeeId">related employee id</param>
        /// <returns>true if user created</returns>
        public bool CreateUser(string username, string password, string employeeId)
        {
            //TODO : check
            string id = Guid.NewGuid().ToString();
            return CreateUser(id, username, password, UserStatus.Active, employeeId);
        }

        /// <summary>
        /// Create new user
        /// </summary>
        /// <param name="userId">user id</param>
        /// <param name="username">username</param>
        /// <param name="password">password</param>
        /// <param name="employeeId">related employee id</param>
        /// <returns>true if user created</returns>
        public bool CreateUser(string userId, string username, string password, string employeeId)
        {
            return CreateUser(userId, username, password, UserStatus.Active, employeeId);
        }

        /// <summary>
        /// Create new user
        /// </summary>
        /// <param name="userId">user id</param>
        /// <param name="username">username</param>
        /// <param name="password">password</param>
        /// <param name="status"><see cref="UserStatus"/></param>
        /// <param name="employeeId">related employee id</param>
        /// <returns>true if user created</returns> 
        public bool CreateUser(string userId, string username, string password, UserStatus status, string employeeId)
        {
            User user = new User();
            user.EmployeeID = employeeId;
            user.ID = userId;
            user.Password = password;
            user.Status = status;
            user.Username = username;

            return CreateUser(user);
        }

        /// <summary>
        /// Obsolete user
        /// </summary>
        /// <param name="username">username</param>
        /// <returns>true if obsoleted successfully</returns>
        public bool DeleteUser(string username)
        {
            User user = GetUserByUsername(username);
            if (user != null)
            {
                return DeleteUser(user);
            }
            //TODO: Handle this case
            throw new Exception("Cannot find user");
        }

        /// <summary>
        /// Obsolete user
        /// </summary>
        /// <param name="user"><see cref="User"/></param>
        /// <returns>true if obsoleted successfully</returns>
        public bool DeleteUser(User user)
        {
            user.DirtyFlag = DirtyFlag.Delete;
            return UpdateUserInfo(user);
        }

        /// <summary>
        /// Update user's info
        /// </summary>
        /// <param name="updatedUserInfo">Updated <see cref="User"/></param>
        /// <returns></returns>
        public bool UpdateUserInfo(User updatedUserInfo)
        {
            TraceUtil.Write(TRACING_CATEGORY, "UpdateUserInfo : Start", DateTime.Now);
            //this method was called directly
            if (updatedUserInfo.DirtyFlag == DirtyFlag.None)
                updatedUserInfo.DirtyFlag = DirtyFlag.Update;

            switch (updatedUserInfo.DirtyFlag)
            {
                case DirtyFlag.Insert:
                case DirtyFlag.Update:
                    break;
                case DirtyFlag.Delete:
                    updatedUserInfo.Status = UserStatus.Obsoleted;
                    break;
                case DirtyFlag.None:
                default:
                    throw new Exception("Unknown operation");
            }

            GeneralDatabaseProvider con = new GeneralDatabaseProvider(DatabaseConstants.AdministrationDatabase);
            ParametersCollection p = new ParametersCollection();
            p.AddParameter(new Parameter(PARAM_USERNAME, updatedUserInfo.Username, ParameterType.String));
            p.AddParameter(new Parameter(PARAM_EMPLOYEE_ID, updatedUserInfo.EmployeeID, ParameterType.String));
            p.AddParameter(new Parameter(PARAM_PASSWORD, updatedUserInfo.Password, ParameterType.String));
            p.AddParameter(new Parameter(PARAM_USER_ID, updatedUserInfo.ID, ParameterType.String));
            p.AddParameter(new Parameter(PARAM_USER_STATUS, ((int)updatedUserInfo.Status), ParameterType.Int));

            int recCount = con.Save(ERP.Framework.Components.DatabaseHelper.CommandType.StoredProcedure, SP_UPD_INS_USER_INFO, p);

            TraceUtil.Write(TRACING_CATEGORY, "UpdateUserInfo : End", DateTime.Now);

            return recCount > 0;
        }
         * */
    }
}
